package jp.co.nes.awssupport.access.dao;

import java.time.YearMonth;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBQueryExpression;
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBScanExpression;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;

import jp.co.nes.awssupport.common.base.CommonException;
import jp.co.nes.awssupport.common.bean.CompileProgressHeaderBean;
import jp.co.nes.awssupport.common.utility.AwsDynamoDBHelper;
import jp.co.nes.awssupport.common.utility.DateUtil;

/**
 * 集計進捗状況ヘッダDAOです。
 */
public class CompileProgressHeaderDao {

    /**
     * デフォルトコンストラクタです。
     */
    public CompileProgressHeaderDao() {
    }

    /**
     * テーブルを作成します。
     *
     * @param rc ReadCapacityUnits
     * @param wc WriteCapacityUnits
     */
    public void createTable(long rc, long wc) {
        AwsDynamoDBHelper helper = new AwsDynamoDBHelper();
        helper.createTable(CompileProgressHeaderBean.class, rc, wc);
    }

    /**
     * 集計進捗状況ヘッダリスト(全件)を返却します。<br>
     * 該当データが存在しない場合は、空のリストを返却します。
     *
     * @return 集計進捗状況ヘッダリスト
     */
    public List<CompileProgressHeaderBean> getList() {
        return getList(false);
    }

    /**
     * 引数に該当する集計進捗状況ヘッダをConsistentReadで読み込み、返却します。<br>
     * 該当データが存在しない場合は、nullを返却します。
     *
     * @param targetYearMonth 処理対象年月
     * @return 集計進捗状況ヘッダ
     */
    public CompileProgressHeaderBean getWithConsistentRead(YearMonth targetYearMonth) {
        return get(targetYearMonth, true);
    }

    /**
     * 集計進捗状況ヘッダを保存します。
     *
     * @param bean 集計進捗状況ヘッダ
     */
    public void save(CompileProgressHeaderBean bean) {
        AwsDynamoDBHelper helper = new AwsDynamoDBHelper();
        helper.save(bean);
    }

    /**
     * 集計進捗状況ヘッダリストを保存します。
     *
     * @param list 集計進捗状況ヘッダリスト
     */
    public void save(List<CompileProgressHeaderBean> list) {
        list.stream().parallel().forEach(bean -> {
            // parallelで処理を実施する。
            AwsDynamoDBHelper helper = new AwsDynamoDBHelper();
            helper.save(bean);
        });
    }

    /**
     * 集計進捗状況ヘッダリストを削除します。
     *
     * @param list 集計進捗状況ヘッダリスト
     */
    public void delete(List<CompileProgressHeaderBean> list) {
        list.stream().forEach(bean -> {
            // parallelで処理を実施する。
            AwsDynamoDBHelper helper = new AwsDynamoDBHelper();
            helper.delete(bean);
        });
    }

    /**
     * 集計進捗状況ヘッダリスト(全件)を返却します。<br>
     * 該当データが存在しない場合は、空のリストを返却します。
     *
     * @param isConsistentRead true: ConsistentReadで読み込む, false: ConsistentReadで読み込まない。
     * @return 集計進捗状況ヘッダリスト
     */
    private List<CompileProgressHeaderBean> getList(boolean isConsistentRead) {
        DynamoDBScanExpression scanExpression = new DynamoDBScanExpression();
        scanExpression.setConsistentRead(isConsistentRead);

        // 件数が少ないのでscanでも問題なし。
        AwsDynamoDBHelper helper = new AwsDynamoDBHelper();
        List<CompileProgressHeaderBean> scanList = helper.scan(CompileProgressHeaderBean.class, scanExpression);
        if (scanList == null) {
            scanList = new ArrayList<>();
        }
        return scanList;
    }

    /**
     * 引数に該当する集計進捗状況ヘッダを返却します。<br>
     * 該当データが存在しない場合は、nullを返却します。
     *
     * @param targetYearMonth 処理対象年月
     * @param isConsistentRead true: ConsistentReadで読み込む, false: ConsistentReadで読み込まない。
     * @return 集計進捗状況ヘッダ
     */
    private CompileProgressHeaderBean get(YearMonth targetYearMonth, boolean isConsistentRead) {
        String keyConditionExpression = "targetYearMonth = :targetYearMonth";
        DynamoDBQueryExpression<CompileProgressHeaderBean> queryExpression = new DynamoDBQueryExpression<>();
        queryExpression.setKeyConditionExpression(keyConditionExpression);
        queryExpression.setConsistentRead(isConsistentRead);

        Map<String, AttributeValue> attrValMap = new HashMap<>();
        attrValMap.put(":targetYearMonth", new AttributeValue().withS(DateUtil.toString(targetYearMonth)));
        queryExpression.setExpressionAttributeValues(attrValMap);

        // queryは条件にプライマリキーの設定が必要。
        CompileProgressHeaderBean result = null;
        AwsDynamoDBHelper helper = new AwsDynamoDBHelper();
        List<CompileProgressHeaderBean> queryList = helper.query(CompileProgressHeaderBean.class, queryExpression);
        if (queryList != null && !queryList.isEmpty()) {
            int size = queryList.size();
            if (size == 1) {
                result = queryList.get(0);
            } else {
                throw new CommonException("queryList is wrong(size=" + size + ")");
            }
        }
        return result;
    }
}
